package com.joe.blockview.ui;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.joe.blockview.R;
import com.joe.blockview.listener.OnDragTouchListener;
import com.joe.blockview.model.Block;
import com.joe.blockview.model.Connection;
import com.joe.blockview.utils.ConnectManager;
import com.joe.blockview.utils.ScreenUtils;
import com.joe.keyboard.KeyBoardView;
import com.joe.keyboard.KeyItemClickListener;

import java.lang.ref.WeakReference;
import java.util.List;

public class WorkSpace extends NonPropagatingViewGroup {
    private static final String TAG = WorkSpace.class.getSimpleName();

    public Block block = new Block();
    private ConnectManager connectManager = new ConnectManager();

    private int trashTop = 820;
    private int trashLeft = 28;


    public WorkSpace(Context context) {
        super(context);
        init();
    }

    public WorkSpace(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public WorkSpace(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private ImageView img;

    public void addTrash() {
        img = new ImageView(getContext());
        img.setImageDrawable(getResources().getDrawable(R.drawable.block_trash_img));
        addView(img);
    }


    private void init() {
        addTrash();
        draggerlistener.setOnDraggableClickListener(new OnDragTouchListener.OnDraggableClickListener() {

            private boolean isFirst = true;

            @Override
            public void onMove(View v, int left, int top) {
                //如果有关联，则取消关联
                BlockView blockView = (BlockView) v;
                Connection preConnection = blockView.getConnection().getPreConnection();
                if (preConnection != null) {
                    //取消相关连的关联
                    Connection cn1 = preConnection.getTagConnection();
                    Connection cn2 = preConnection.getNextConnection();
                    //区分内部向下，还是外部向下
                    if (cn1 == blockView.getConnection()) {
                        preConnection.setCanConnect(true);
                        preConnection.connectionTag(null);
                    } else if (cn2 == blockView.getConnection()) {
                        preConnection.setNextConnect(true);
                        preConnection.connectionNext(null);
                    }

                    //取消其本身的上关联
                    blockView.getConnection().setPreCanConnect(true);
                    blockView.getConnection().connectionPre(null);

                    //测量移除部分的高度
                    updateOutLineView(preConnection.getTagBlockView());
                }

                //如果是内部输入，则取消内部关联
                if (blockView.getConnection().getType() == 4) {
                    Connection icn = blockView.getConnection().getInputConnection();
                    if (icn != null) {
                        icn.setInputCanConnect(true);
                        icn.connectionInput(null);

                        blockView.getConnection().setInputCanConnect(true);
                        blockView.getConnection().connectionInput(null);
                    }
                }

                //先取消关联，再移动层次
                if (isFirst) {
                    bringToFrot((BlockView) v);

                    isFirst = false;
                }

                //检测附近是否有可用连接

            }

            @Override
            public void onDragged(View v, int left, int top) {
                isFirst = true;
                BlockView blockView = (BlockView) v;
                //检测控件是否拖动到删除位置，如果是，则执行删除操作
                Rect viewRect = new Rect();
                v.getGlobalVisibleRect(viewRect);
                View otherView = img;
                Rect otherViewRect = new Rect();
                otherView.getGlobalVisibleRect(otherViewRect);
                //判断是否有和trash重叠部分
                if (Rect.intersects(viewRect, otherViewRect)) {
                    //删除View
                    deletBlock(blockView);
                    return;
                }

                //检测附近是否有可用连接，有则连接上，无则更新定位
                blockView.getConnection().getWorkspacePoint().x = v.getLeft();
                blockView.getConnection().getWorkspacePoint().y = v.getTop();

                List<Connection> connections = block.getAllConnections();
                connections = connectManager.filterConnnection(connections, blockView.getConnection());

                if (blockView.getConnection().getType() == 4) {
                    Connection incon = connectManager.findInputConnection(connections, blockView.getResources(), blockView.getConnection());
                    if (incon != null && incon.getInputCanConnect()) {
                        dealInputConnection(v, incon, blockView);
                    } else {
                        //更新view定位
                        transferBlock(blockView);
                        //刷新界面
                        requestLayout();
                    }
                } else {
                    //获取有可能上关联的连接
                    Connection co = connectManager.findCloseUpConnection(connections, blockView.getResources(), blockView.getConnection());
                    //获取有可能下关联的连接,先获取最后一个blockView的定位
                    Connection lastConnection = connectManager.getLastBlockView(blockView.getConnection());
                    //先更新lastConnection坐标
                    lastConnection.getWorkspacePoint().x = lastConnection.getTagBlockView().getLeft();
                    lastConnection.getWorkspacePoint().y = lastConnection.getTagBlockView().getTop();

                    Connection co2 = connectManager.findCloseDownConnection(connections, blockView.getResources(), lastConnection);

                    Connection co3 = connectManager.findNextDownConnection(connections, blockView.getResources(), blockView.getConnection());

                    if (co3 != null && co3.getNextConnect()) {
                        dealNextConnection(v, co3, blockView);
                    } else if (co != null && co.canConnect() && blockView.getConnection().getPreCanConnect() && blockView.getConnection().getType() != 0) {
                        dealTagConnection(v, co, blockView);
                    } else if (co2 != null && co2.getPreCanConnect() && lastConnection.canConnect() && lastConnection.getType() != -1) {
                        dealPreConnection(v, co2, lastConnection);
                    } else {
                        //更新view定位
                        transferBlock(blockView);
                        requestLayout();
                    }
                }


            }

            @Override
            public void onClick(View v) {
                isFirst = true;
                if (keyBoardView != null) {
                    keyBoardView.setVisibility(GONE);
                }
            }
        });

    }

    private WeakReference<BlockView> selectedBlock;
    private KeyBoardView keyBoardView;

    public void addKeyBoard(KeyBoardView keyBoardView) {
        this.keyBoardView = keyBoardView;
        this.keyBoardView.addClickListener(new KeyItemClickListener() {
            @Override
            public void onItemClick(int type, String num) {
                if (selectedBlock != null) {
                    if (selectedBlock.get().getcView() instanceof TextView) {
                        BlockView blockView = (BlockView) selectedBlock.get();
                        TextView tv = (TextView) selectedBlock.get().getcView();
                        if (type == 0) {
                            if (blockView.getStep() != "0") {
                                num = blockView.getStep() + num;
                                blockView.setStep(num);
                            } else {
                                blockView.setStep(num);
                            }

                        } else if (type == 1) {
                            blockView.setStep(num);
                        } else if (type == 2) {
                            if (blockView.getStep() != "" && blockView.getStep() != "-" && blockView.getStep() != "0") {
                                num = blockView.getStep() + num;
                                blockView.setStep(num);
                            }
                        } else {
                            if (blockView.getStep().length() > 1) {
                                num = blockView.getStep().substring(0, blockView.getStep().length() - 1);
                                blockView.setStep(num);
                            } else {
                                blockView.setStep("0");
                            }
                        }

                        tv.setText(blockView.getStep());
                    }
                }
            }
        });
    }


    //测量控件宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {

            if (getChildAt(i) instanceof BlockView) {
                BlockView blockGroup = (BlockView) getChildAt(i);
                blockGroup.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            } else if (getChildAt(i) instanceof ImageView) {
                ImageView img = (ImageView) getChildAt(i);
                img.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            } else {
                View img = getChildAt(i);
                img.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
            }

            // Determine this BlockGroup's bounds in view coordinates and extend boundaries
            // accordingly. Do NOT use mHelper.workspaceToVirtualViewCoordinates below, since we
            // want the bounding box independent of scroll offset.
//            blockGroup.temp.top = 0;
//            blockGroup.temp.left = 0;
//            blockGroup.temp.right = width;
//            blockGroup.temp.bottom = height;
        }


        setMeasuredDimension(width, height);
    }


    //子控件排布
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        //清空Connection
        block.clearConnections();
        int childCount = getChildCount();

        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                continue;
            }

            if (child instanceof BlockView) {
                //重新添加Connection

                final BlockView bg = (BlockView) child;
                block.addConnection(bg.getConnection());

                //设置拖拽监听
                bg.setOnTouchListener(draggerlistener);

                //设置圆View点击事件
                View v = bg.getcView();
                if (v != null) {
                    v.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (keyBoardView != null) {
                                selectedBlock = new WeakReference<BlockView>(bg);
                                keyBoardView.setVisibility(VISIBLE);
                            }
                        }
                    });
                }

                int left = bg.temp.left;
                int top = bg.temp.top;
                int right = left + bg.getMeasuredWidth();
                int bottom = top + bg.getMeasuredHeight();
                child.layout(left, top, right, bottom);
                //mTemp.y = mTemp.y + bg.getMeasuredHeight()+1;
            } else if (child instanceof ImageView) {
                ImageView bg = (ImageView) child;

                //固定位置，不随布局的滑动而改变
                int left = trashLeft + getScrollX();
                int top = trashTop + getScrollY();
                int right = left + (int) ScreenUtils.getPxFromDp(bg.getResources(), 50);
                int bottom = top + (int) ScreenUtils.getPxFromDp(bg.getResources(), 50);
                child.layout(left, top,
                        right, bottom);
            } else {
                View bg = child;
                int left = 0;
                int top = 0;
                int right = left + bg.getMeasuredWidth();
                int bottom = top + bg.getMeasuredHeight();
                child.layout(left, top, right, bottom);
            }
        }
    }


    // Allowed zoom scales.
    private static final float[] ZOOM_SCALES = new float[]{0.25f, 0.5f, 1.0f, 2.0f};
    private static final int INIT_ZOOM_SCALES_INDEX = 2;
    // Scale and zoom in/out factor.
    private int mCurrentZoomScaleIndex = INIT_ZOOM_SCALES_INDEX;
    private float mViewScale = ZOOM_SCALES[INIT_ZOOM_SCALES_INDEX];


    int[] mLastTouchLocation = new int[2];

    boolean isSingle = true;//是否单个手指


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (scanAble && mScaleGestureDetector != null) {
            mScaleGestureDetector.onTouchEvent(event);
            if (mScaleGestureDetector.isInProgress()) {
                return true;
            }
        }

        if (mTapGestureDetector != null) {
            mTapGestureDetector.onTouchEvent(event);
        }


        //手工滑动
        final int action = event.getAction();

        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                isSingle = true;
                img.bringToFront();
                mLastTouchLocation[0] = x;
                mLastTouchLocation[1] = y;
                break;
            case MotionEvent.ACTION_MOVE:
                if (isSingle) {
                    int sx = mLastTouchLocation[0];
                    int sy = mLastTouchLocation[1];
                    //计算出移动的距离
                    int dx = x - sx;
                    int dy = y - sy;
                    //记下最后这个点的位置
                    mLastTouchLocation[0] = x;
                    mLastTouchLocation[1] = y;

                    //计算出目标的x,y 坐标点，由于View要求滑动的方向，应该与手指滑动的方向一致，所以这里 应该取反，可以想象下 在你手指往下滑动的时候，你这个view的滑动坐标是需要减少的
                    int tx = getScrollX() + (-dx);
                    int ty = getScrollY() + (-dy);

                    //TODO 检测y的边界，让他 不能滑倒底部继续滑动
                    //滑动到 目标坐标
                    //动态获取边界限制

                    //int widgetH = connectManager.getWidgetHight(block.getAllConnections());

                    int of = connectManager.getWidgetHight(block.getAllConnections());
                    if (tx > -500 && tx < 500 && ty > -of - 500 && ty < of + 500) {
                        scrollTo(tx, ty);
                        //必须 调用重画，不然他只是滑动，并有在界面上显示
                        requestLayout();
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                isSingle = false;
                break;
        }

        return true;
    }

    //添加子控件的拖动事件
    private OnDragTouchListener draggerlistener = new OnDragTouchListener();


    //由于抖动问题，暂时无法使用，同时position还没有处理
    private boolean scanAble = false;
    private ScaleGestureDetector mScaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.SimpleOnScaleGestureListener() {

        // Focus point at the start of the pinch gesture. This is used for computing proper scroll
        // offsets during scaling, as well as for simultaneous panning.
        private float mStartFocusX;
        private float mStartFocusY;
        // View scale at the beginning of the gesture. This is used for computing proper scroll
        // offsets during scaling.
        private float mStartScale;
        // View scroll offsets at the beginning of the gesture. These provide the reference point
        // for adjusting scroll in response to scaling and panning.
        private int mStartScrollX;
        private int mStartScrollY;

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            mStartFocusX = detector.getFocusX();
            mStartFocusY = detector.getFocusY();

            mStartScrollX = getScrollX();
            mStartScrollY = getScrollY();

            mStartScale = mViewScale;
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {

            final float oldViewScale = mViewScale;

            final float scaleFactor = detector.getScaleFactor();
            mViewScale *= scaleFactor;

            if (mViewScale < ZOOM_SCALES[0]) {
                mCurrentZoomScaleIndex = 0;
                mViewScale = ZOOM_SCALES[mCurrentZoomScaleIndex];
            } else if (mViewScale > ZOOM_SCALES[ZOOM_SCALES.length - 1]) {
                mCurrentZoomScaleIndex = ZOOM_SCALES.length - 1;
                mViewScale = ZOOM_SCALES[mCurrentZoomScaleIndex];
            } else {
                // find nearest zoom scale
                float minDist = Float.MAX_VALUE;
                // If we reach the end the last one was the closest
                int index = ZOOM_SCALES.length - 1;
                for (int i = 0; i < ZOOM_SCALES.length; i++) {
                    float dist = Math.abs(mViewScale - ZOOM_SCALES[i]);
                    if (dist < minDist) {
                        minDist = dist;
                    } else {
                        // When it starts increasing again we've found the closest
                        index = i - 1;
                        break;
                    }
                }
                mCurrentZoomScaleIndex = index;
            }


            setScaleX(mViewScale);
            setScaleY(mViewScale);


            // Compute scroll offsets based on difference between original and new scaling factor
            // and the focus point where the gesture started. This makes sure that the scroll offset
            // is adjusted to keep the focus point in place on the screen unless there is also a
            // focus point shift (see next scroll component below).
            final float scaleDifference = mViewScale - mStartScale;
            final int scrollScaleX = (int) (scaleDifference * mStartFocusX);
            final int scrollScaleY = (int) (scaleDifference * mStartFocusY);

            // Compute scroll offset based on shift of the focus point. This makes sure the view
            // pans along with the focus.
            final int scrollPanX = (int) (mStartFocusX - detector.getFocusX());
            final int scrollPanY = (int) (mStartFocusY - detector.getFocusY());

            // Apply the computed scroll components for scale and panning relative to the scroll
            // coordinates at the beginning of the gesture.
            scrollTo(mStartScrollX + scrollScaleX + scrollPanX,
                    mStartScrollY + scrollScaleY + scrollPanY);
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {

        }

    });

    private GestureDetector mTapGestureDetector = new GestureDetector(getContext(), new TapGestureListener());

    private class TapGestureListener extends GestureDetector.SimpleOnGestureListener {
        public boolean onSingleTapUp(MotionEvent e) {
            return callOnClick();
        }
    }

    ////======================================================================
    ///======================block连接，重新定位模块==========================
    ///=======================================================================

    /**
     * 处理向下关联
     */
    private void dealPreConnection(View v, Connection co2, Connection lastConnection) {
        if (co2 == lastConnection)
            return;
        //向上关联
        co2.connectionPre(lastConnection);
        co2.setPreCanConnect(false);

        //向下关联
        lastConnection.setCanConnect(false);
        lastConnection.connectionTag(co2);


        int scdistence = 130;
        if (lastConnection.getType() == 2 || lastConnection.getType() == 3) {
            scdistence = 230 + lastConnection.getTagBlockView().getBLength();
        }


        //更新view定位
        lastConnection.getTagBlockView().setPosition((int) co2.getWorkspacePoint().x, (int) co2.getWorkspacePoint().y - scdistence, (int) co2.getWorkspacePoint().x + lastConnection.getTagBlockView().getMeasuredWidth(), (int) co2.getWorkspacePoint().y - scdistence + lastConnection.getTagBlockView().getSelfHeight() + lastConnection.getTagBlockView().getBLength());
        lastConnection.getWorkspacePoint().x = (int) co2.getWorkspacePoint().x;
        lastConnection.getWorkspacePoint().y = (int) co2.getWorkspacePoint().y - scdistence;
        if (lastConnection.getType() == 2) {
            Connection inp = lastConnection.getInputConnection();
            if (inp != null) {
                BlockView blockViewp = inp.getTagBlockView();
                blockViewp.setPosition(lastConnection.getTagBlockView().getPosition().left + 180, lastConnection.getTagBlockView().getPosition().top + 25, lastConnection.getTagBlockView().getPosition().right + 180, lastConnection.getTagBlockView().getPosition().bottom + 25);
                inp.getWorkspacePoint().x = lastConnection.getWorkspacePoint().x + 180;
                inp.getWorkspacePoint().y = lastConnection.getWorkspacePoint().y + 25;
            }
        }

        updateDownOutLineView(lastConnection.getTagBlockView());

        requestLayout();
    }

    /**
     * 出路向上关联
     */
    private void dealTagConnection(View v, Connection co, BlockView blockView) {
        if (co == blockView.getConnection())
            return;
        //向下关联
        co.connectionTag(blockView.getConnection());
        co.setCanConnect(false);

        //向上关联
        blockView.getConnection().setPreCanConnect(false);
        blockView.getConnection().connectionPre(co);

        int scdistence = 130;
        if (co.getType() == 2 || co.getType() == 3) {
            scdistence = 230 + co.getTagBlockView().getBLength();
        }


        //更新view定位
        blockView.setPosition((int) co.getWorkspacePoint().x, (int) co.getWorkspacePoint().y + scdistence, (int) co.getWorkspacePoint().x + v.getMeasuredWidth(), (int) co.getWorkspacePoint().y + scdistence + v.getMeasuredHeight());
        blockView.getConnection().getWorkspacePoint().x = (int) co.getWorkspacePoint().x;
        blockView.getConnection().getWorkspacePoint().y = (int) co.getWorkspacePoint().y + scdistence;


        if (blockView.getConnection().getType() == 2) {
            Connection inp = blockView.getConnection().getInputConnection();
            if (inp != null) {
                BlockView blockViewp = inp.getTagBlockView();
                blockViewp.setPosition(blockView.getPosition().left + 180, blockView.getPosition().top + 25, blockView.getPosition().right + 180, blockView.getPosition().bottom + 25);
                inp.getWorkspacePoint().x = blockView.getConnection().getWorkspacePoint().x + 180;
                inp.getWorkspacePoint().y = blockView.getConnection().getWorkspacePoint().y + 25;
            }
        }

        updateInlineView(blockView);

        updateOutLineView(co.getTagBlockView());

        //刷新界面
        requestLayout();
    }

    //////////////////////////////////////////////////////////////////
    //////////////////////////-----针对block2对接block1-------////////
    //////////////////////////----上部分固定，下部分移动-----/////////
    //////////////////////////////////////////////////////////////////

    /**
     * block2
     *
     * @param blockView
     * @param
     * @return
     */
    public void updateInlineView(BlockView blockView) {
        Connection tagCon = blockView.getConnection().getTagConnection();
        Connection nextCon = blockView.getConnection().getNextConnection();
        Connection tags = blockView.getConnection();
        if (tags.getType() == 2) {
            Connection inp = tags.getInputConnection();
            if (inp != null) {
                BlockView blockViewp = inp.getTagBlockView();
                blockViewp.setPosition(tags.getTagBlockView().getPosition().left + 180, tags.getTagBlockView().getPosition().top + 25, tags.getTagBlockView().getPosition().right + 180, tags.getTagBlockView().getPosition().bottom + 25);
                inp.getWorkspacePoint().x = tags.getWorkspacePoint().x + 180;
                inp.getWorkspacePoint().y = tags.getWorkspacePoint().y + 25;
            }
        }
        if (tagCon != null) {
            BlockView tag = tagCon.getTagBlockView();
            int scdistence = 130;
            if (blockView.getConnection().getType() == 2 || blockView.getConnection().getType() == 3) {
                scdistence = 230 + blockView.getBLength();
            }
            //更新定位
            tag.setPosition((int) blockView.getConnection().getWorkspacePoint().x, (int) blockView.getConnection().getWorkspacePoint().y + scdistence, (int) blockView.getConnection().getWorkspacePoint().x + tag.getMeasuredWidth(), (int) blockView.getConnection().getWorkspacePoint().y + scdistence + tag.getMeasuredHeight());
            tag.getConnection().getWorkspacePoint().x = (int) blockView.getConnection().getWorkspacePoint().x;
            tag.getConnection().getWorkspacePoint().y = (int) blockView.getConnection().getWorkspacePoint().y + scdistence;

            updateInlineView(tag);
        }
        if (nextCon != null) {
            BlockView next = nextCon.getTagBlockView();
            //更新定位
            next.setPosition((int) blockView.getConnection().getWorkspacePoint().x + 20, (int) blockView.getConnection().getWorkspacePoint().y + 130, (int) blockView.getConnection().getWorkspacePoint().x + 20 + next.getMeasuredWidth(), (int) blockView.getConnection().getWorkspacePoint().y + 130 + next.getMeasuredHeight());
            next.getConnection().getWorkspacePoint().x = (int) blockView.getConnection().getWorkspacePoint().x + 20;
            next.getConnection().getWorkspacePoint().y = (int) blockView.getConnection().getWorkspacePoint().y + 130;
            updateInlineView(next);
        }
    }

    /**
     * block1
     *
     * @param
     */
    public void updateOutLineView(BlockView blockView) {
        Connection con1 = blockView.getConnection();
        if (con1.getType() == 2 || con1.getType() == 3) {
            blockView.requestLayout();
            blockView.invalidate();

            Connection tag = blockView.getConnection().getTagConnection();
            if (tag != null) {
                //先更新tag定位
                int scdistence = 130;
                if (con1.getType() == 2 || con1.getType() == 3) {
                    scdistence = 230 + con1.getTagBlockView().getBLength();
                } else {
                    scdistence = 130;
                }

                //更新tag定位
                tag.getTagBlockView().setPosition((int) con1.getWorkspacePoint().x, (int) con1.getWorkspacePoint().y + scdistence, (int) con1.getWorkspacePoint().x + tag.getTagBlockView().getMeasuredWidth(), (int) con1.getWorkspacePoint().y + scdistence + tag.getTagBlockView().getMeasuredHeight());
                tag.getWorkspacePoint().x = (int) con1.getWorkspacePoint().x;
                tag.getWorkspacePoint().y = (int) con1.getWorkspacePoint().y + scdistence;

                if (tag.getType() == 2) {
                    Connection inp = tag.getInputConnection();
                    if (inp != null) {
                        BlockView blockViewp = inp.getTagBlockView();
                        blockViewp.setPosition(tag.getTagBlockView().getPosition().left + 180, tag.getTagBlockView().getPosition().top + 25, tag.getTagBlockView().getPosition().right + 180, tag.getTagBlockView().getPosition().bottom + 25);
                        inp.getWorkspacePoint().x = tag.getWorkspacePoint().x + 180;
                        inp.getWorkspacePoint().y = tag.getWorkspacePoint().y + 25;
                    }
                }

                //更新接下来部分
                updateInlineView(tag.getTagBlockView());
            }
        }

        Connection pre = con1.getPreConnection();
        if (pre != null) {
            updateOutLineView(pre.getTagBlockView());
        }
    }

    ////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////


    ////////////////////////////////////////////////////////////////
    /////////////////////-----上部分移动，下部分固定-----///////////
    ///////////////////////////////////////////////////////////////

    public void updateDownOutLineView(BlockView blockView) {
        Connection con = blockView.getConnection();
        if (con.getType() == 2 || con.getType() == 3) {
            updateDownInlineView(blockView);
        }

        //由下往上递归
        Connection preCon = con.getPreConnection();
        if (preCon != null) {
            //更新定位
            int scdistence = 130;
            if (preCon.getType() == 2 || preCon.getType() == 3) {
                scdistence = 230 + preCon.getTagBlockView().getBLength();
            }

            //更新view定位
            preCon.getTagBlockView().setPosition((int) con.getWorkspacePoint().x, (int) con.getWorkspacePoint().y - scdistence, (int) con.getWorkspacePoint().x + preCon.getTagBlockView().getMeasuredWidth(), (int) con.getWorkspacePoint().y - scdistence + preCon.getTagBlockView().getBLength() + preCon.getTagBlockView().getSelfHeight());
            preCon.getWorkspacePoint().x = (int) con.getWorkspacePoint().x;
            preCon.getWorkspacePoint().y = (int) con.getWorkspacePoint().y - scdistence;

            updateDownOutLineView(preCon.getTagBlockView());
        }
    }


    public void updateDownInlineView(BlockView blockView) {
        Connection tagCon = blockView.getConnection().getTagConnection();
        Connection nextCon = blockView.getConnection().getNextConnection();
        Connection tags = blockView.getConnection();
        if (tags.getType() == 2) {
            Connection inp = tags.getInputConnection();
            if (inp != null) {
                BlockView blockViewp = inp.getTagBlockView();
                blockViewp.setPosition(tags.getTagBlockView().getPosition().left + 180, tags.getTagBlockView().getPosition().top + 25, tags.getTagBlockView().getPosition().right + 180, tags.getTagBlockView().getPosition().bottom + 25);
                inp.getWorkspacePoint().x = tags.getWorkspacePoint().x + 180;
                inp.getWorkspacePoint().y = tags.getWorkspacePoint().y + 25;
            }
        }
        if (tagCon != null) {
            BlockView tag = tagCon.getTagBlockView();
            int scdistence = 130;
            if (blockView.getConnection().getType() == 2 || blockView.getConnection().getType() == 3) {
                scdistence = 230 + blockView.getBLength();
            }
            //更新定位
            tag.setPosition((int) blockView.getConnection().getWorkspacePoint().x, (int) blockView.getConnection().getWorkspacePoint().y + scdistence, (int) blockView.getConnection().getWorkspacePoint().x + tag.getMeasuredWidth(), (int) blockView.getConnection().getWorkspacePoint().y + scdistence + tag.getMeasuredHeight());
            tag.getConnection().getWorkspacePoint().x = (int) blockView.getConnection().getWorkspacePoint().x;
            tag.getConnection().getWorkspacePoint().y = (int) blockView.getConnection().getWorkspacePoint().y + scdistence;


            updateInlineView(tag);
        }
        if (nextCon != null) {
            BlockView next = nextCon.getTagBlockView();
            //更新定位
            next.setPosition((int) blockView.getConnection().getWorkspacePoint().x + 20, (int) blockView.getConnection().getWorkspacePoint().y + 130, (int) blockView.getConnection().getWorkspacePoint().x + 20 + next.getMeasuredWidth(), (int) blockView.getConnection().getWorkspacePoint().y + 130 + next.getMeasuredHeight());
            next.getConnection().getWorkspacePoint().x = (int) blockView.getConnection().getWorkspacePoint().x + 20;
            next.getConnection().getWorkspacePoint().y = (int) blockView.getConnection().getWorkspacePoint().y + 130;
            updateInlineView(next);
        }
    }

    /////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////

    /**
     * 块的整体移动，重新定位
     */
    public void transferBlock(BlockView blockView) {
        int l = blockView.getLeft();
        int t = blockView.getTop();
        int r = blockView.getRight();
        int b = blockView.getBottom();
        blockView.setPosition(l, t, r, b);
        blockView.getConnection().getWorkspacePoint().x = l;
        blockView.getConnection().getWorkspacePoint().y = t;

        if (blockView.getConnection().getType() == 2) {
            Connection inp = blockView.getConnection().getInputConnection();
            if (inp != null) {
                BlockView blockViewp = inp.getTagBlockView();
                blockViewp.setPosition(blockViewp.getLeft(), blockViewp.getTop(), blockViewp.getRight(), blockViewp.getBottom());
                inp.getWorkspacePoint().x = blockViewp.getLeft();
                inp.getWorkspacePoint().y = blockViewp.getTop();
            }
        }

        if (blockView.getConnection().getNextConnection() != null) {
            transferBlock(blockView.getConnection().getNextConnection().getTagBlockView());
        }

        if (blockView.getConnection().getTagConnection() != null) {
            transferBlock(blockView.getConnection().getTagConnection().getTagBlockView());
        }
    }

    /**
     * 处理内部输入关联
     */
    private void dealInputConnection(View v, Connection incon, BlockView blockView) {
        if (incon == blockView.getConnection())
            return;
        //添加对外关联
        incon.setInputCanConnect(false);
        incon.connectionInput(blockView.getConnection());
        //添加对内关联
        blockView.getConnection().setInputCanConnect(false);
        blockView.getConnection().connectionInput(incon);

        //更新定位
        blockView.setPosition((int) incon.getWorkspacePoint().x + 180, (int) incon.getWorkspacePoint().y + 25, (int) incon.getWorkspacePoint().x + 180 + v.getMeasuredWidth(), (int) incon.getWorkspacePoint().y + 25 + v.getMeasuredHeight());
        blockView.getConnection().getWorkspacePoint().x = (int) incon.getWorkspacePoint().x + 180;
        blockView.getConnection().getWorkspacePoint().y = (int) incon.getWorkspacePoint().y + 25;
        //刷新界面
        requestLayout();
    }

    /**
     * 处理内部向下关联
     */
    private void dealNextConnection(View v, Connection co3, BlockView blockView) {
        if (co3 == blockView.getConnection())
            return;
        //向下关联
        co3.connectionNext(blockView.getConnection());
        co3.setNextConnect(false);

        //向上关联
        blockView.getConnection().setPreCanConnect(false);
        blockView.getConnection().connectionPre(co3);


        int scdistence = 130;

        //更新view定位
        blockView.setPosition((int) co3.getWorkspacePoint().x + 20, (int) co3.getWorkspacePoint().y + scdistence, (int) co3.getWorkspacePoint().x + 20 + v.getMeasuredWidth(), (int) co3.getWorkspacePoint().y + scdistence + v.getMeasuredHeight());
        blockView.getConnection().getWorkspacePoint().x = (int) co3.getWorkspacePoint().x + 20;
        blockView.getConnection().getWorkspacePoint().y = (int) co3.getWorkspacePoint().y + scdistence;

        if (blockView.getConnection().getType() == 2) {
            Connection inp = blockView.getConnection().getInputConnection();
            if (inp != null) {
                BlockView blockViewp = inp.getTagBlockView();
                blockViewp.setPosition(blockView.getPosition().left + 180, blockView.getPosition().top + 25, blockView.getPosition().right + 180, blockView.getPosition().bottom + 25);
                inp.getWorkspacePoint().x = blockView.getConnection().getWorkspacePoint().x + 180;
                inp.getWorkspacePoint().y = blockView.getConnection().getWorkspacePoint().y + 25;
            }
        }

        updateInlineView(blockView);
        updateOutLineView(co3.getTagBlockView());

        requestLayout();
    }


    /**
     * 移动内部控件到最前端
     */
    private void bringToFrot(BlockView tag) {
        tag.bringToFront();
        if (tag.getConnection().getInputConnection() != null) {
            tag.getConnection().getInputConnection().getTagBlockView().bringToFront();
        }
        if (tag.getConnection().getNextConnection() != null) {
            bringToFrot(tag.getConnection().getNextConnection().getTagBlockView());
        }
        if (tag.getConnection().getTagConnection() != null) {
            bringToFrot(tag.getConnection().getTagConnection().getTagBlockView());
        }

    }

    /**
     * 删除拖动到trash的block
     */
    public void deletBlock(BlockView blockView) {
        Connection con = blockView.getConnection();
        if (con.getNextConnection() != null) {
            deletBlock(con.getNextConnection().getTagBlockView());
        }

        if (con.getTagConnection() != null) {
            deletBlock(con.getTagConnection().getTagBlockView());
        }

        if (con.getInputConnection() != null) {
            //执行删除操作
            removeView(con.getInputConnection().getTagBlockView());
            block.getAllConnections().remove(con.getInputConnection());
        }

        //执行删除操作
        removeView(blockView);
        block.getAllConnections().remove(blockView.getConnection());
    }


    //////===============================================================
    /////==============拖动条功能处理模块================================
    ////=================================================================

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        setWillNotDraw(false);
        setHorizontalScrollBarEnabled(true);
        setVerticalScrollBarEnabled(true);
    }

    @Override
    protected int computeHorizontalScrollExtent() {
        return getMeasuredWidth();
    }

    @Override
    protected int computeHorizontalScrollOffset() {
        return getScrollX();
    }

    @Override
    protected int computeHorizontalScrollRange() {
        return getMeasuredWidth() + 500;
    }

    @Override
    protected int computeVerticalScrollExtent() {
        return getMeasuredHeight();
    }

    @Override
    protected int computeVerticalScrollOffset() {
        return getScrollY();
    }

    @Override
    protected int computeVerticalScrollRange() {
        return getMeasuredHeight() + 500 + connectManager.getWidgetHight(block.getAllConnections());
    }

}
